#include <iostream>
using namespace std;

#define SIX

/**
 *  所有指针的值的实际数据类型，不管是整型、浮点型、字符型，还是其他的数据类型，都是一样的，
 *  都是一个代表内存地址的长的十六进制数。不同数据类型的指针之间唯一的不同是，指针所指向的变量或常量的数据类型不同
 *
 *  其实就是指针加1，实际的地址偏移不同
 *
 *  uint32_t * Ptr1=NULL;
 *  uint32_t * Ptr2=NULL;
 *  uint32_t Array[10]={0};
 *
 *  Ptr1=&(Array[0]);
 *  Ptr2=&(Array[6])
 *
 *  Ptr++;
 *
 *  那么Ptr现在指向了Array[1]
 *
 *  Ptr2-Ptr1 等于 6 就是表示 Ptr2到Ptr1之间有6个元素
 *
 *  同一种类型的指针比较才有意义
 */

#if defined SEVEN

int main()
{
    int* Ptr = NULL;

    cout << "Ptr的值是" << Ptr << endl;   // 会输出0值

    return 0;
}

#elif defined TWO

int main(void)
{
    int  Array[]   = { 10, 20, 30, 40, 50 };
    int* ArrayPtr1 = NULL;
    int* ArrayPtr2 = NULL;

    ArrayPtr1      = &(Array[1]);
    ArrayPtr2      = &(Array[3]);

    if (ArrayPtr1 < ArrayPtr2)
    {
        cout << "ArrayPtr1 指向的元素在 ArrayPtr2 指向的元素之前" << endl;
    }
    else
    {
        cout << "ArrayPtr1 指向的元素 不在 ArrayPtr2 指向的元素之前" << endl;
    }
    return 0;
}

#elif defined THREE

const int MAX = 3;

int main(void)
{
    int  Var[MAX] = { 10, 20, 30 };
    int* Ptr      = nullptr;

    Ptr           = Var;

    for (int i = 0; i < MAX; i++)
    {
        cout << "Var[" << i << "]的内存地址为";
        cout << Ptr << endl;

        cout << "Var[" << i << "]的值为";
        cout << *Ptr << endl;

        Ptr++;
    }

    return 0;
}

#elif defined FOUR

const int MAX = 3;

int main(void)
{
    int Var[MAX] = { 10, 20, 30 };

    for (int i = 0; i < MAX; i++)
    {
        cout << "Var[" << i << "]: " << Var[i] << endl;
    }

    for (int i = 0; i < MAX; i++)
    {
        // *Var=i;  //OK
        // Var++;   Error 因为Var是一个指向数组开头的常量   就是说数组名对应一个指针常量 (int * const p) 就是指针的指向不能被改变
        *(Var + i) = i;   // OK                                 但通过这个指针修改变量的值是允许的
    }
    for (int i = 0; i < MAX; i++)
    {
        cout << "Var[" << i << "]: " << Var[i] << endl;
    }
    return 0;
}

#elif defined FIVE

/**
 * 指针数组的概念  就是数组里面存储指向int或者char或者其它数据类型的指针。  下面声明一个指向整型的指针数组
 * int * PtrArray[MAX];    这个数组的类型是 int * （就是整型指针）
 */

const int MAX = 3;

int main(void)
{
    int  Var[MAX] = { 10, 100, 200 };
    int* Ptr[MAX];

    for (int i = 0; i < MAX; i++)
    {
        Ptr[i] = &(Var[i]);   // 赋值为整数的地址
    }
    for (int i = 0; i < MAX; i++)
    {
        cout << "Value Of Var[" << i << "]=";
        cout << *(Ptr[i]) << endl;
    }
    return 0;
}

#elif defined SIX

const int MAX = 4;

int main(void)
{
    // 指针数组  就是数组里面的成员是  const char * （即 常量字符指针   指向的内容为常量  但是指针指向的位置可以改变）
    const char* Name[MAX] = { "Zara Ali", "Hina Ali", "Nuha Ali", "Sara Ali" };

    for (int i = 0; i < MAX; i++)
    {
        cout << "Value Of Name[" << i << "]=";
        cout << Name[i] << endl;
    }
    return 0;
}


#endif

/**
 *  C++中 常量指针 和 指针常量
 *
 *  常量指针 (Pointer To Constant)
 *  就是指向常量数据的指针,不能通过指针修改所指向对象的值
 *  语法 const int * p;   或者 int const * p;
 *  但是指针p可以被修改，就是指向其它对象   但是不能通过该指针修改被指向对象的值
 *
 *  int a=10;
 *  int b=20;
 *  const int * p=NULL;
 *  p=&a;  //OK
 *  p=&b;  //OK
 *  *p =30; //Error
 *
 *
 *  指针常量(Constant Pointer)
 *  就是指针本身是常量，不能改变指针的指向
 *  语法 int * const p=&a;  //只能指向a,但是可以通过p修改a的值
 *
 *  int a=10;
 *  int b=20;
 *  int * const p=&a;
 *  *p=30;  //OK
 *   p=&b;   //Error
 *
 *
 *  合起来还有一个 叫做 指向常量的指针常量
 *  语法  int const * const p=&a;
 *    但是这个指针必须被初始化
 *    既不能改变指向，也不能通过指针修改数据
 */